defold_log("functions_graphics.cmake:")

# Returns a CMake list of exported graphics adapter symbols for a given
# TARGET_PLATFORM-like tuple (e.g., x86_64-macos, arm64-linux, x86_64-win32).
#
# The selection mirrors waf_dynamo.py: platform_graphics_libs_and_symbols.
# It considers the toggles WITH_OPENGL, WITH_VULKAN, WITH_DX12, WITH_WEBGPU
# if they are defined in the including scope; otherwise assumes OFF.
#
# Usage:
#   include(functions_graphics)
#   defold_get_graphics_symbols(_SYMS "x86_64-macos")
#   # _SYMS now contains a semicolon-separated list, e.g. "GraphicsAdapterOpenGL;GraphicsAdapterVulkan"

function(defold_get_graphics_symbols OUT_VAR PLATFORM)
    # Read feature toggles with default OFF if not defined
    set(_WITH_OPENGL  OFF)
    set(_WITH_VULKAN  OFF)
    set(_WITH_DX12    OFF)
    set(_WITH_WEBGPU  OFF)
    if(DEFINED WITH_OPENGL AND WITH_OPENGL)
        set(_WITH_OPENGL ON)
    endif()
    if(DEFINED WITH_VULKAN AND WITH_VULKAN)
        set(_WITH_VULKAN ON)
    endif()
    if(DEFINED WITH_DX12 AND WITH_DX12)
        set(_WITH_DX12 ON)
    endif()
    if(DEFINED WITH_WEBGPU AND WITH_WEBGPU)
        set(_WITH_WEBGPU ON)
    endif()

    set(_use_opengl   OFF)
    set(_use_opengles OFF)
    set(_use_vulkan   OFF)

    # Base selection per platform
    if("${PLATFORM}" MATCHES "^(arm64-macos|x86_64-macos|arm64-nx64)$")
        set(_use_opengl ${_WITH_OPENGL})
        set(_use_vulkan ON)
    elseif("${PLATFORM}" MATCHES "^(arm64-linux)$")
        set(_use_opengles ON)
        set(_use_vulkan ${_WITH_VULKAN})
    else()
        set(_use_opengl ON)
        set(_use_vulkan ${_WITH_VULKAN})
    endif()

    # Compute symbols
    set(_SYMS)

    # Platform overrides
    if(PLATFORM STREQUAL "arm64-nx64")
        list(APPEND _SYMS GraphicsAdapterVulkan)
    elseif(PLATFORM STREQUAL "x86_64-ps4")
        list(APPEND _SYMS GraphicsAdapterPS4)
    elseif(PLATFORM STREQUAL "x86_64-ps5")
        list(APPEND _SYMS GraphicsAdapterPS5)
    else()
        if(_use_opengles)
            list(APPEND _SYMS GraphicsAdapterOpenGLES)
        elseif(_use_opengl)
            list(APPEND _SYMS GraphicsAdapterOpenGL)
        endif()
        if(_use_vulkan)
            list(APPEND _SYMS GraphicsAdapterVulkan)
        endif()
        if(_WITH_DX12 AND PLATFORM STREQUAL "x86_64-win32")
            list(APPEND _SYMS GraphicsAdapterDX12)
        endif()
        if(_WITH_WEBGPU AND ("${PLATFORM}" MATCHES "^(js-web|wasm-web|wasm_pthread-web)$"))
            list(APPEND _SYMS GraphicsAdapterWebGPU)
        endif()
    endif()

    set(${OUT_VAR} "${_SYMS}" PARENT_SCOPE)
endfunction()


function(defold_target_link_graphics target platform)
    set(options)
    set(oneValueArgs SCOPE)
    set(multiValueArgs)
    cmake_parse_arguments(DGL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
    if(NOT DGL_SCOPE)
        set(DGL_SCOPE PRIVATE)
    endif()

    if(NOT platform)
        message(FATAL_ERROR "functions_graphics: platform argument is required")
    endif()

    # Compute Waf-like mapping variables (STLIB_* + GL/Vulkan lists)
    string(REGEX REPLACE "^[^-]+-" "" _PLAT_OS "${platform}")

    # Optional feature toggles affecting mappings
    set(_WITH_WAGYU OFF)
    set(_WITH_VULKAN_VALIDATION OFF)
    if(DEFINED WITH_WAGYU AND WITH_WAGYU)
        set(_WITH_WAGYU ON)
    endif()
    if(DEFINED WITH_VULKAN_VALIDATION AND WITH_VULKAN_VALIDATION)
        set(_WITH_VULKAN_VALIDATION ON)
    endif()

    # Static groups (keep local to this function/file)
    set(_STLIB_GRAPHICS           graphics;graphics_transcoder_basisu;basis_transcoder)
    set(_STLIB_GRAPHICS_OPENGLES  graphics_opengles;graphics_transcoder_basisu;basis_transcoder)
    set(_STLIB_GRAPHICS_VULKAN    graphics_vulkan;graphics_transcoder_basisu;basis_transcoder)
    set(_STLIB_GRAPHICS_DX12      graphics_dx12;graphics_transcoder_basisu;basis_transcoder)
    if(_WITH_WAGYU)
        set(_STLIB_GRAPHICS_WEBGPU graphics_webgpu_wagyu;graphics_transcoder_basisu;basis_transcoder)
    else()
        set(_STLIB_GRAPHICS_WEBGPU graphics_webgpu;graphics_transcoder_basisu;basis_transcoder)
    endif()
    set(_STLIB_GRAPHICS_NULL      graphics_null;graphics_transcoder_null)

    # GLFW mapping
    if(_PLAT_OS MATCHES "^(macos|linux|win32)$")
        set(_STLIB_DMGLFW glfw3)
    else()
        set(_STLIB_DMGLFW dmglfw)
    endif()

    # On Windows, our prebuilt static libs use a "lib" prefix (lib*.lib).
    # Prefix our own graphics library names accordingly to match filenames.
    if(_PLAT_OS STREQUAL "win32")
        foreach(_grp IN ITEMS _STLIB_GRAPHICS _STLIB_GRAPHICS_OPENGLES _STLIB_GRAPHICS_VULKAN _STLIB_GRAPHICS_DX12 _STLIB_GRAPHICS_WEBGPU _STLIB_GRAPHICS_NULL _STLIB_DMGLFW)
            set(_tmp_list)
            foreach(_name ${${_grp}})
                if(_name AND NOT _name MATCHES "^lib")
                    list(APPEND _tmp_list "lib${_name}")
                else()
                    list(APPEND _tmp_list "${_name}")
                endif()
            endforeach()
            set(${_grp} ${_tmp_list})
        endforeach()
    endif()

    # GL/GLES
    unset(OPENGL)
    unset(OPENGLES)
    unset(FRAMEWORK_OPENGL)
    unset(OPENGL_LINKFLAGS)
    unset(FRAMEWORK_DMGLFW)
    if("${_PLAT_OS}" MATCHES "^(linux|android)$")
        set(OPENGL   GL;GLU)
        set(OPENGLES EGL;GLESv1_CM;GLESv2)
    elseif(_PLAT_OS STREQUAL "win32")
        set(OPENGL_LINKFLAGS opengl32.lib;glu32.lib)
    elseif(_PLAT_OS STREQUAL "macos")
        set(FRAMEWORK_OPENGL OpenGL;AGL)
    elseif(_PLAT_OS STREQUAL "ios")
        set(FRAMEWORK_DMGLFW QuartzCore;OpenGLES;CoreVideo;CoreGraphics)
    endif()

    # Vulkan
    unset(VULKAN)
    unset(FRAMEWORK_VULKAN)
    unset(VULKAN_LINKFLAGS)
    if(_PLAT_OS STREQUAL "macos")
        if(_WITH_VULKAN_VALIDATION)
            set(VULKAN vulkan)
        else()
            set(VULKAN MoltenVK)
        endif()
        set(FRAMEWORK_VULKAN Metal;IOSurface;QuartzCore)
    elseif(_PLAT_OS STREQUAL "ios")
        set(VULKAN MoltenVK)
        set(FRAMEWORK_VULKAN Metal;IOSurface)
    elseif(_PLAT_OS STREQUAL "linux")
        set(VULKAN vulkan;X11-xcb)
        if(_WITH_VULKAN_VALIDATION AND platform STREQUAL "arm64-linux")
            list(APPEND VULKAN VkLayer_khronos_validation)
        endif()
    elseif(_PLAT_OS STREQUAL "android")
        set(VULKAN vulkan)
    elseif(_PLAT_OS STREQUAL "win32")
        set(VULKAN_LINKFLAGS vulkan-1.lib)
    endif()

    # Feature toggles with default OFF
    set(_WITH_OPENGL  OFF)
    set(_WITH_VULKAN  OFF)
    set(_WITH_DX12    OFF)
    set(_WITH_WEBGPU  OFF)
    if(DEFINED WITH_OPENGL AND WITH_OPENGL)
        set(_WITH_OPENGL ON)
    endif()
    if(DEFINED WITH_VULKAN AND WITH_VULKAN)
        set(_WITH_VULKAN ON)
    endif()
    if(DEFINED WITH_DX12 AND WITH_DX12)
        set(_WITH_DX12 ON)
    endif()
    if(DEFINED WITH_WEBGPU AND WITH_WEBGPU)
        set(_WITH_WEBGPU ON)
    endif()

    set(_use_opengl   OFF)
    set(_use_opengles OFF)
    set(_use_vulkan   OFF)

    if("${platform}" MATCHES "^(arm64-macos|x86_64-macos|arm64-nx64)$")
        set(_use_opengl ${_WITH_OPENGL})
        set(_use_vulkan ON)
    elseif("${platform}" MATCHES "^(arm64-linux)$")
        set(_use_opengles ON)
        set(_use_vulkan ${_WITH_VULKAN})
    else()
        set(_use_opengl ON)
        set(_use_vulkan ${_WITH_VULKAN})
    endif()

    set(_DEFOLD_GRAPHICS_LIBS)

    if(platform STREQUAL "arm64-nx64")
        list(APPEND _DEFOLD_GRAPHICS_LIBS GRAPHICS_VULKAN DMGLFW VULKAN)
    elseif(platform STREQUAL "x86_64-ps4")
        set(_DEFOLD_GRAPHICS_LIBS GRAPHICS)
    elseif(platform STREQUAL "x86_64-ps5")
        set(_DEFOLD_GRAPHICS_LIBS GRAPHICS)
    else()
        if(_use_opengles)
            list(APPEND _DEFOLD_GRAPHICS_LIBS GRAPHICS_OPENGLES DMGLFW OPENGLES)
        elseif(_use_opengl)
            # on mobile, we should really start using the libgraphics_opengles.a
            if("${platform}" MATCHES "^(arm64-android|armv7-android)$")
                list(APPEND _DEFOLD_GRAPHICS_LIBS OPENGLES)
            else()
                list(APPEND _DEFOLD_GRAPHICS_LIBS OPENGL)
            endif()
            list(APPEND _DEFOLD_GRAPHICS_LIBS GRAPHICS DMGLFW)
        endif()
        if(_use_vulkan)
            list(APPEND _DEFOLD_GRAPHICS_LIBS GRAPHICS_VULKAN DMGLFW VULKAN)
        endif()
        if(_WITH_DX12 AND platform STREQUAL "x86_64-win32")
            list(APPEND _DEFOLD_GRAPHICS_LIBS GRAPHICS_DX12)
        endif()
        if(_WITH_WEBGPU AND ("${platform}" MATCHES "^(js-web|wasm-web|wasm_pthread-web)$"))
            list(APPEND _DEFOLD_GRAPHICS_LIBS GRAPHICS_WEBGPU)
        endif()
    endif()

    set(_link_libs)
    set(_link_opts)

    foreach(item IN LISTS _DEFOLD_GRAPHICS_LIBS)
        if(item STREQUAL "GRAPHICS")
            list(APPEND _link_libs ${_STLIB_GRAPHICS})
        elseif(item STREQUAL "GRAPHICS_OPENGLES")
            list(APPEND _link_libs ${_STLIB_GRAPHICS_OPENGLES})
        elseif(item STREQUAL "GRAPHICS_VULKAN")
            list(APPEND _link_libs ${_STLIB_GRAPHICS_VULKAN})
        elseif(item STREQUAL "GRAPHICS_DX12")
            list(APPEND _link_libs ${_STLIB_GRAPHICS_DX12})
        elseif(item STREQUAL "GRAPHICS_WEBGPU")
            list(APPEND _link_libs ${_STLIB_GRAPHICS_WEBGPU})
        elseif(item STREQUAL "GRAPHICS_NULL")
            list(APPEND _link_libs ${_STLIB_GRAPHICS_NULL})
        elseif(item STREQUAL "DMGLFW")
            list(APPEND _link_libs ${_STLIB_DMGLFW})
            if(DEFINED FRAMEWORK_DMGLFW)
                foreach(fw IN LISTS FRAMEWORK_DMGLFW)
                    list(APPEND _link_libs "-framework ${fw}")
                endforeach()
            endif()
        elseif(item STREQUAL "OPENGL")
            if(DEFINED OPENGL)
                list(APPEND _link_libs ${OPENGL})
            endif()
            if(DEFINED FRAMEWORK_OPENGL)
                foreach(fw IN LISTS FRAMEWORK_OPENGL)
                    list(APPEND _link_libs "-framework ${fw}")
                endforeach()
            endif()
            if(DEFINED OPENGL_LINKFLAGS)
                list(APPEND _link_opts ${OPENGL_LINKFLAGS})
            endif()
        elseif(item STREQUAL "OPENGLES")
            if(DEFINED OPENGLES)
                list(APPEND _link_libs ${OPENGLES})
            endif()
        elseif(item STREQUAL "VULKAN")
            if(DEFINED VULKAN)
                list(APPEND _link_libs ${VULKAN})
            endif()
            if(DEFINED FRAMEWORK_VULKAN)
                foreach(fw IN LISTS FRAMEWORK_VULKAN)
                    list(APPEND _link_libs "-framework ${fw}")
                endforeach()
            endif()
            if(DEFINED VULKAN_LINKFLAGS)
                list(APPEND _link_opts ${VULKAN_LINKFLAGS})
            endif()
        endif()
    endforeach()

    if(_link_libs)
        target_link_libraries(${target} ${DGL_SCOPE} ${_link_libs})
    endif()
    if(_link_opts)
        target_link_options(${target} ${DGL_SCOPE} ${_link_opts})
    endif()

    # For web targets, also include the GLFW JS shim library from the SDK
    if("${platform}" MATCHES "^(js-web|wasm-web|wasm_pthread-web)$")
        set(_glfw_js "${DEFOLD_SDK_ROOT}/ext/lib/${platform}/js/library_glfw.js")
        if(EXISTS "${_glfw_js}")
            target_link_options(${target} ${DGL_SCOPE} "--js-library" "${_glfw_js}")
        else()
            message(STATUS "functions_graphics: library_glfw.js not found at ${_glfw_js}")
        endif()
    endif()
endfunction()
